package com.zrt.utils.date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.core.date.DateUnit;

/**
 * @author 庄锐涛
 * @version 1.0.0
 */
public class DateUtil extends cn.hutool.core.date.DateUtil {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final static ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();

    /**
     * 日期格式化规则(yyyy-MM-dd)
     */
    public final static String DefaultDateFormatPattern = "yyyy-MM-dd";
    /**
     * 日志类型时间格式化规则(yyyyMMdd)
     */
    public final static String DefaultLogDateFormatPattern = "yyyyMMdd";
    /**
     * 日志类型时间格式化规则(yyyyMMddHHmmss)
     */
    public final static String DefaultLogDateTimeFormatPattern = "yyyyMMddHHmmss";
    /**
     * 时间格式化规则(HH:mm:ss)
     */
    public final static String DefaultTimeFormatPattern = "HH:mm:ss";
    /**
     * 完整日期格式话规则(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DefaultDateTimeFormatPattern = "yyyy-MM-dd HH:mm:ss";

    /**
     * 完整日期格式话规则(yyyy-MM-dd HH:mm:ss.S)
     */
    public final static String DefaultDateTimeSFormatPattern = "yyyy-MM-dd HH:mm:ss.S";
    /**
     * 完整日期格式话规则(yyyy-MM-dd HH:mm:ss.SSS)
     */
    public final static String DefaultDateTimeSssFormatPattern = "yyyy-MM-dd HH:mm:ss.SSS";
    /**
     * 日期格式话规则(yyyy-MM-dd HH:mm:ss.SSSSSSSSS)
     */
    public final static String DefaultDateTimeSssssssssFormatPattern = "yyyy-MM-dd HH:mm:ss.SSSSSSSSS";
    /**
     * 日期格式化规则类(yyyy-MM)
     */
    public final static DateTimeFormatter DefaultMonthFormat = DateTimeFormatter.ofPattern("yyyy-MM");
    /**
     * 日期格式化规则类(yyyy-MM-dd)
     */
    public final static DateTimeFormatter DefaultDateFormat = DateTimeFormatter.ofPattern(DefaultDateFormatPattern);
    /**
     * 日志类型时间格式化规则类(yyyyMMdd)
     */
    public final static DateTimeFormatter DefaultLogDateFormat = DateTimeFormatter.ofPattern(DefaultLogDateFormatPattern);
    /**
     * 日志类型时间格式化规则类(yyyyMMddHHmmss)
     */
    public final static DateTimeFormatter DefaultLogDateTimeFormat = DateTimeFormatter.ofPattern(DefaultLogDateTimeFormatPattern);
    /**
     * 时间格式化规则类(HH:mm:ss)
     */
    public final static DateTimeFormatter DefaultTimeFormat = DateTimeFormatter.ofPattern(DefaultTimeFormatPattern);
    /**
     * 完整日期格式化类(yyyy-MM-dd HH:mm:ss)
     */
    public final static DateTimeFormatter DefaultDateTimeFormat = DateTimeFormatter.ofPattern(DefaultDateTimeFormatPattern);
    /**
     * 完整日期格式化类,带毫秒(yyyy-MM-dd HH:mm:ss.S)
     */
    public final static DateTimeFormatter DefaultDateTimeSFormat = DateTimeFormatter.ofPattern(DefaultDateTimeSFormatPattern);
    /**
     * 完整日期格式化类,带毫秒(yyyy-MM-dd HH:mm:ss.SSS)
     */
    public final static DateTimeFormatter DefaultDateTimeSssFormat = DateTimeFormatter.ofPattern(DefaultDateTimeSssFormatPattern);
    /**
     * 完整日期格式化类,带纳秒(yyyy-MM-dd HH:mm:ss.SSSSSSSSS)
     */
    public final static DateTimeFormatter DefaultDateTimeSssssssssFormat = DateTimeFormatter.ofPattern(DefaultDateTimeSssssssssFormatPattern);

    /**
     * 获取当前时间
     */
    public static LocalDateTime getCurrentTime() {
        return LocalDateTime.now();
    }

    /**
     * 将日期格式字符串转换为日期对象和
     */
    public static Date parseToDate(String textDate) {
        return toDatetime(LocalDate.parse(textDate));
    }

    /**
     * <pre>
     * 将本地日期对象转化为日期对象
     *
     * 注意:如果本地日期对象为空,返回空对象日期
     * <pre/>
     */
    public static Date toDatetime(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        return Date.from(localDate.atStartOfDay().atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     *  计算两个日期的时间间隔
     *  date
     * </pre>
     */
    public static long between(Date date1, Date date2, DateUnit dateUnit) {
        if (date1 == null || date2 == null) {
            throw new RuntimeException("Null not permit in here");
        }
        return cn.hutool.core.date.DateUtil.between(date1, date2, dateUnit);
    }

    /**
     * <pre>
     *  计算传入月份的第一天的 0点0时0分
     * </pre>
     */
    public static Date getFirstDayOfMonth(Date date) {
        if (date == null) {
            return null;
        }
        return Date.from(
                LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(
                        0).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     * 将日期对象{@link Date}转换为本地日期时间对象{@link LocalDateTime}
     * 日期对象为空时,返回空的本地日期时间对象
     * </pre>
     *
     * @param date 日期对象
     * @return 本地日期时间对象
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        if (date == null) {
            return null;
        } else {
            return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID);
        }
    }


    /**
     * <pre>
     * 计算传入月份的最后一天的0时0分0秒
     * <pre/>
     */
    public static Date getLastDayOfMonth(Date date) {
        if (date == null) {
            return null;
        }
        //由于Date的API拿最大日期都是31天  所以这里先转为
        LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID);
        LocalDate localDate = localDateTime.toLocalDate();
        int lastDay = localDate.lengthOfMonth();
        return Date.from(
                LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID).withDayOfMonth(lastDay).withHour(0).withSecond(0).withMinute(0).withNano(
                        0).atZone(DEFAULT_ZONE_ID).toInstant());
    }


    /**
     * <pre>
     *  将当前的日期 置为当天的开始时间
     * </pre>
     */
    public static Date getStarOfDay() {
        return Date.from(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     *  将当前日期置为当天的最后时间  如 2021-07-30 23:59:59
     * </pre>
     */
    public static Date getEndOfDay() {
        return Date.from(LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).plusSeconds(-1).atZone(DEFAULT_ZONE_ID).toInstant());
    }


    /**
     * <pre>
     *  获取昨日的最后时间  如2021-07-29 23:59:59
     * </pre>
     */
    public static Date getEndOfYesterDay() {
        return Date.from(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).plusSeconds(-1).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     *  获取offest后的当前时刻
     * </pre>
     */
    public static Date getTomorrow(Integer offest) {
        return Date.from(LocalDateTime.now().plusDays(offest).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     * 获取offest天前的当前时刻
     * </pre>
     */
    public static Date getYesterday(Integer offest) {
        return Date.from(LocalDateTime.now().plusDays(-1 * offest).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     *  获取当天+ - offest天前开始的时间
     * </pre>
     */
    public static Date getOffsetstarOfDay(Integer offest) {
        return Date.from(
                LocalDateTime.now().plusDays(offest).withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * <pre>
     * 按照指定的格式化对象格式化日期对象,转换为字符串
     *
     * 注意:如果日期为空,返回空字符串对象("")
     *
     * 常用格式对象:
     * {@link #DefaultDateFormat} ===> "yyyy-MM-dd"
     * {@link #DefaultTimeFormat} ===> "HH:mm:ss"
     * {@link #DefaultDateTimeFormat} ===> "yyyy-MM-dd HH:mm:ss"
     * {@link #DefaultDateTimeSssFormat} ===> "yyyy-MM-dd HH:mm:ss.SSS"
     * {@link #DefaultLogDateTimeFormat} ===> "yyyyMMddHHmmss"
     * {@link #DefaultLogDateFormatPattern} ===> "yyyyMMdd"
     * </pre>
     *
     * @param formatter 格式化规则对象
     * @param date 日期时间
     * @return 字符串
     */
    public static String formatToString(DateTimeFormatter formatter, Date date) {
        return formatToString(formatter, toLocalDateTime(date));
    }

    /**
     * @param formatter 格式化规则对象
     * @param localDateTime 本地日期时间
     * @return 字符串
     */
    public static String formatToString(DateTimeFormatter formatter, LocalDateTime localDateTime) {
        if (formatter == null) {
            return "";
        } else if (localDateTime == null) {
            return "";
        } else {
            return localDateTime.format(formatter);
        }
    }

    /**
     * <pre>
     * 获取月份的最大天数
     * <pre/>
     */
    public static Integer getLengthDays(Date date) {
        if (date == null) {
            return 0;
        }
        return LocalDateTime.ofInstant(date.toInstant(), DEFAULT_ZONE_ID).toLocalDate().lengthOfMonth();
    }

    /**
     * <pre>
     * 返回昨日同时刻
     * </pre>
     */
    public static Date beforeDay() {
        return cn.hutool.core.date.DateUtil.yesterday().toJdkDate();
    }

    /**
     * <pre>
     * 返回明日相同时刻
     * <pre/>
     */
    public static Date nextDay() {
        return cn.hutool.core.date.DateUtil.tomorrow().toJdkDate();
    }

    /**
     * <pre>
     * 将日期时间字符串根据"日期时间格式化对象"转换为日期对象
     *
     * 仅支持字符串是日期类型,不支持时间类型
     * 格式示例:
     * "yyyyMMdd"
     * "yyyy-MM-dd"
     * "dd MM yyyy"
     * "uuuu-MM-dd"
     * </pre>
     *
     * @param formatterPattern 格式化类型规则
     * @param textDatetime 字符串
     * @return 日期对象, 时间字段补0
     */
    public static Date parseToDate(String formatterPattern, String textDatetime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatterPattern);
        LocalDate localDate = LocalDate.parse(textDatetime, formatter);
        return toDatetime(localDate);
    }
}
